/**************************************************************************************************
	$Header: /pub/cvsroot/mydns/src/mydns/conf.c,v 1.12 2002/07/29 06:34:02 bboy Exp $
	conf.c: Routines to read the configuration file.

	Copyright (C) 2002  Don Moore <bboy@bboy.net>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at Your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**************************************************************************************************/

#include "named.h"

#include <pwd.h>
#include <grp.h>

CONF	*Conf = (CONF *)NULL;									/* Config options */
int	opt_daemon = 0;											/* Run in background? (-d, --daemon) */
char	*opt_conf = MYDNS_CONF;									/* Location of config file (-c, --conf) */
uid_t	perms_uid = 0;												/* User permissions */
gid_t	perms_gid = 0;												/* Group permissions */
time_t task_timeout;												/* Task timeout */
int	axfr_enabled = 0;											/* Enable AXFR? */
int	tcp_enabled = 0;											/* Enable TCP? */


/* Returns 1 for "[Yy](es)", "[Tt](rue)", "1", or "(o)[Nn]" */
#define  atobool(str)   \
   (str && (str[0] == 'Y' || str[0] == 'y' || str[0] == 'T' || str[0] == 't' || \
   str[0] == '1' || str[1] == 'n' || str[1] == 'N'))

/* Default config values */
static CONF defConfig[] = {
	/* Name					Alt name	Value							Description									Next */
	{	"-",					NULL,		NULL,							"DATABASE INFORMATION",					NULL },
	{	"mysql-host",		NULL,		"localhost",				"MySQL server hostname",				NULL },
	{	"mysql-user",		NULL,		"user",						"MySQL username",							NULL },
	{	"mysql-password",	NULL,		"password",					"MySQL password",							NULL },
	{	"database",			NULL,		PACKAGE_NAME,				"MyDNS database name",					NULL },

	{	"-",					NULL,		NULL,							"GENERAL OPTIONS",						NULL },

	{	"user",				NULL,		"nobody",					"Run with the permissions of this user",		NULL },
	{	"group",				NULL,		"nogroup",					"Run with the permisisons of this group",		NULL },
	{	"listen",			"bind",	"*",							"Listen on these addresses ('*'=any)",	NULL},
	{	"port",				NULL,		"53",							"Listen on this port number",	NULL},

	{	"-",					NULL,		NULL,							"CACHE OPTIONS",					NULL },

	{	"cache-size",		NULL,		"16384",						"Maximum number of elements stored in the cache",	NULL },
	{	"cache-expire",	NULL,		"60",							"Number of seconds after which cached data expires", NULL },

	{	"-",					NULL,		NULL,							"ESOTERICA",					NULL },
	{	"log",				NULL,		"LOG_DAEMON",				"Facility to use for program output (LOG_*/stderr)",		NULL },
	{	"pidfile",			NULL,		"/var/run/"PACKAGE_NAME".pid",	"Path to PID file",						NULL },
	{	"timeout",			NULL,		"5",							"Number of seconds after which queries time out", NULL },
	{	"multicpu",			NULL,		"1",							"Number of CPUs installed on your system",	NULL },
	{	"allow-axfr",		NULL,		"no",							"Should AXFR be enabled?",				NULL },
	{	"allow-tcp",		NULL,		"no",							"Should TCP be enabled?",				NULL },
	{	"soa-table",		NULL,		MYDNS_SOA_TABLE,			"Name of table containing SOA records",	NULL },
	{	"rr-table",			NULL,		MYDNS_RR_TABLE,			"Name of table containing RR data",			NULL },
	{	"ptr-table",		NULL,		MYDNS_PTR_TABLE,			"Name of table containing PTR records",	NULL },

	{	NULL,					NULL,		NULL,							NULL,											NULL }
};


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	DUMP_CONFIG
	Output configuration info (in a sort of config-file format).
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
dump_config(void)
{
	time_t time_now = time(NULL);
	int len = 0, w = 0, n;
	char pair[512];
	CONF *c;

	printf("\
##
##  "MYDNS_CONF"
##  %.24s
##  %s
##
", ctime(&time_now), _("For more information, see mydns.conf(5)."));

	/* Look up description for configured variables and determine longest name/value pair length */
	for (n = 0; defConfig[n].name; n++)
	{
		char *value = conf_get(&Conf, defConfig[n].name);

		c = &defConfig[n];
		if (!value)
			value = c->value;
		if ((len = strlen(c->name) + (value ? strlen(value) : 0)) > w)
			w = len;
	}
	w += strlen(" = ");

	for (n = 0; defConfig[n].name; n++)
	{
		char *value = conf_get(&Conf, defConfig[n].name);

		c = &defConfig[n];
		if (!value)
			value = c->value;
		if (c->name[0] == '-')
			printf("\n\n%-*.*s\t# %s\n\n", w, w, " ", c->desc);
		else
		{
			snprintf(pair, sizeof(pair), "%s = %s", c->name, value);
			printf("%-*.*s\t# %s\n", w, w, pair, c->desc);
		}
	}
	printf("\n");
}
/*--- dump_config() -----------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	CONF_SET_LOGGING
	Sets the logging type and opens the syslog connection if necessary.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
conf_set_logging(void)
{
	char logtype[80];

	strncpy(logtype, conf_get(&Conf, "log"), sizeof(logtype)-1);
	strtolower(logtype);

	if (!err_stderr)
		closelog();
	err_stderr = 0;

	if (!strcmp(logtype, "stderr")) err_stderr = 1;
	else if (!strcmp(logtype, "log_daemon")) error_init(NULL, LOG_DAEMON);
	else if (!strcmp(logtype, "log_local0")) error_init(NULL, LOG_LOCAL0);
	else if (!strcmp(logtype, "log_local1")) error_init(NULL, LOG_LOCAL1);
	else if (!strcmp(logtype, "log_local2")) error_init(NULL, LOG_LOCAL2);
	else if (!strcmp(logtype, "log_local3")) error_init(NULL, LOG_LOCAL3);
	else if (!strcmp(logtype, "log_local4")) error_init(NULL, LOG_LOCAL4);
	else if (!strcmp(logtype, "log_local5")) error_init(NULL, LOG_LOCAL5);
	else if (!strcmp(logtype, "log_local6")) error_init(NULL, LOG_LOCAL6);
	else if (!strcmp(logtype, "log_local7")) error_init(NULL, LOG_LOCAL7);
	else Warnx("\"%s\": %s", conf_get(&Conf, "log"), _("unknown logging facility"));
}
/*--- conf_set_logging() ------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	CHECK_CONFIG_FILE_PERMS
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
check_config_file_perms(void)
{
	FILE *fp;

	if ((fp = fopen(opt_conf, "r")))
	{
		Warnx("%s: %s", opt_conf, _("WARNING: config file is readable by unprivileged user"));
		fclose(fp);
	}
}
/*--- check_config_file_perms() -----------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	LOAD_CONFIG
	Load the configuration file.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
load_config(void)
{
	int n;
	struct passwd *pwd = NULL;
	struct group *grp = NULL;

	/* Load config */
	conf_load(&Conf, opt_conf);

	/* Set defaults */
	for (n = 0; defConfig[n].name; n++)
	{
		if (defConfig[n].name[0] == '-')
			continue;
		if (!conf_get(&Conf, defConfig[n].name))
			conf_set(&Conf, defConfig[n].name, defConfig[n].value);
	}

#if HAVE_GETPWUID
	/* Set default for MySQL username to real username if none was provided */
	if (!conf_get(&Conf, "mysql-user"))
	{
		struct passwd *pwd;
		if ((pwd = getpwuid(getuid())) && pwd->pw_name)
		{
			conf_set(&Conf, "mysql-user", pwd->pw_name);
			memset(pwd, 0, sizeof(struct passwd));
		}
	}
#endif

	/* Load user/group perms */
	if (!(pwd = getpwnam(conf_get(&Conf, "user"))))
		Err(_("error loading uid for user `%s'"), conf_get(&Conf, "user"));
	perms_uid = pwd->pw_uid;
	perms_gid = pwd->pw_gid;
	memset(pwd, 0, sizeof(struct passwd));

	if (!(grp = getgrnam(conf_get(&Conf, "group"))) && !(grp = getgrnam("nobody")))
	{
		Warnx(_("error loading gid for group `%s'"), conf_get(&Conf, "group"));
		Warnx(_("using gid %u from user `%s'"), perms_gid, conf_get(&Conf, "user"));
	}
	else
	{
		perms_gid = grp->gr_gid;
		memset(grp, 0, sizeof(struct group));
	}

	/* We call conf_set_logging() again after moving into background, but it's called here
		to report on errors. */
	conf_set_logging();

	/* Set global options */
	task_timeout = atou(conf_get(&Conf, "timeout"));
	axfr_enabled = atobool(conf_get(&Conf, "allow-axfr"));
	tcp_enabled = atobool(conf_get(&Conf, "allow-tcp"));

	/* Set table names if provided */
	mydns_set_soa_table_name(conf_get(&Conf, "soa-table"));
	mydns_set_rr_table_name(conf_get(&Conf, "rr-table"));
	mydns_set_ptr_table_name(conf_get(&Conf, "ptr-table"));
}
/*--- load_config() -----------------------------------------------------------------------------*/

/* vi:set ts=3: */
/* NEED_PO */
